package users

import (
	"encoding/json"
	"fmt"
	"github.com/beego/beego/v2/core/validation"
	"github.com/beego/beego/v2/server/web/pagination"
	"github.com/kingzcheung/carbon"
	"log"
	"strconv"
	"strings"
	"xpms/app/auth/groups"
	"xpms/controllers"
	"xpms/cores"
	"xpms/cores/utils"
)

// 用户管理
type UserController struct {
	controllers.BaseController
}

// @Title 用户
// @Description 分页查询用户数据
// @Param	p		query 	int	true		"第几页"
// @Param	status		query 	string			"用户状态"
// @Param	pageoffset		query 	int			"每页数"
// @Param	keywords		query 	string			"关键字搜索"
// @Success 200 {object} sys.UsersBO   int   int  int
// @Failure 403 user not exist
// @router /page [get]
func (u *UserController) UsersByPage() {
	page, err := u.GetInt("p")
	status := u.GetString("status")
	keywords := u.GetString("keywords")
	if err != nil {
		page = 1
	}
	offset, err := u.GetInt("pageoffset")
	if err != nil {
		offset = 15
	}
	condArr := make(map[string]interface{})
	condArr["status"] = status
	condArr["keywords"] = keywords
	countUser := UserPageCountExec(condArr, page, offset)
	paginator := pagination.SetPaginator(u.Ctx, offset, countUser)
	user := UserPageExec(condArr, page, offset)
	type data struct {
		Users    []UsersBO
		Total    int64
		PageNums int
		Page     int
	}
	d := &data{user, paginator.Nums(), paginator.PageNums(), paginator.Page()}
	var responseEntity cores.ResponseEntity
	u.Data["json"] = responseEntity.Build(d).Data
	u.Ctx.Output.Status = responseEntity.StatusCode
	u.ServeJSON()
}

// @Title 菜单
// @Description 根据用户获取菜单
// @Success 200 {object} groups.GroupsUserPermission
// @Failure 403 菜单不存在
// @router /me/menu [get]
func (u *UserController) MenuByUser() {
	//左侧导航
	_, _, leftNav := groups.ListGroupsUserPermission(u.GetSession("userGroupid").([]string))
	var responseEntity cores.ResponseEntity
	u.Data["json"] = responseEntity.Build(leftNav).Data
	u.ServeJSON()
}

// @Title 权限
// @Description 根据用户获取权限
// @Success 200 {object} groups.GroupsUserPermission
// @Failure 403
// @router /me/permission [get]
func (u *UserController) PermissionByUser() {
	//左侧导航
	condArr := make(map[string]interface{})
	condArr["groupid"] = u.GetSession("userGroupid").([]string)
	condArr["nav"] = 3
	_, _, resources := groups.QueryGroupsRestPermission(condArr)
	var responseEntity cores.ResponseEntity
	u.Data["json"] = responseEntity.Build(resources).Data
	u.ServeJSON()
}

type UserDTO struct {
	Username    string
	Password    string
	Avatar      string
	Status      int
	Realname    string
	Sex         int `json:"Sex,string"`
	Birth       string
	Email       string
	Webchat     string
	Qq          string
	Phone       string
	Tel         string
	Address     string
	Emercontact string
	Emerphone   string
	Departid    int64 `json:"Departid,string"`
	Positionid  int64 `json:"Positionid,string"`
}

// 如果你的 struct 实现了接口 validation.ValidFormer
// 当 StructTag 中的测试都成功时，将会执行 Valid 函数进行自定义验证
func (u *UserDTO) Valid(v *validation.Validation) {
	v.Required(u.Username, "username").Message("登陆账号不能为空")
	v.Required(u.Realname, "realname").Message("用户名不能为空")
	v.Required(u.Email, "email").Message("邮箱不能为空")
	v.Email(u.Email, "email").Message("请输入正确的邮箱格式")
	v.Range(u.Sex, 0, 2, "sex").Message("请选择性别")
	//从时间戳中解析
	if !utils.IsEmpty(u.Birth) {
		Started, err := carbon.CreateFromTimestampString(u.Birth)
		if err != nil || Started.Year < 1971 {
			v.AddError("birth", "生日非日期格式") //将错误信息直接返回 配合前文我写的错误信息拼接字段名，就可以做到直接返回完整的错误提示
		}
	}
}

// @Title CreateUser
// @Description create users
// @Param	body		body 	users.UserDTO	true		"body for user content"
// @Success 200 {int} users.User.Id
// @Failure 403 body is empty
// @router / [post]
func (u *UserController) CreateUser() {
	var f UserDTO
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &f)
	// 开始校验输入值
	valid := validation.Validation{}
	b, err := valid.Valid(&f)
	valid.Required(f.Password, "password").Message("请输入密码")
	if err != nil {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
		u.ServeJSON()
		return
	}
	if !b {
		var validMsg []string
		// validation does not pass
		for _, err := range valid.Errors {
			validMsg = append(validMsg, err.Message)
			log.Println(err.Key, err.Message)
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	userss, err1 := GetUserByUserName(f.Username)
	if err1 != nil || !utils.IsEmpty(userss.Id) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "登陆账号重复"}
		u.ServeJSON()
		return
	}
	//雪花算法ID生成
	id := utils.SnowFlakeId()
	var pro UsersProfile
	pro.Id = id
	pro.Realname = f.Realname
	pro.Sex = f.Sex
	pro.Birth = f.Birth
	pro.Email = f.Email
	pro.Webchat = f.Webchat
	pro.Qq = f.Qq
	pro.Phone = f.Phone
	pro.Tel = f.Tel
	pro.Address = f.Address
	pro.Emercontact = f.Emercontact
	pro.Emerphone = f.Emerphone
	pro.Departid = f.Departid
	pro.Positionid = f.Positionid
	pro.Ip = u.Ctx.Input.IP()

	var user Users
	user.Id = id
	user.Username = f.Username
	user.Password = f.Password

	err = AddUserProfile(user, pro)

	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "员工信息添加成功", "id": fmt.Sprintf("%d", id)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "员工信息添加失败"}
	}
	u.ServeJSON()
}

// @Title UpdateUser
// @Description  UpdateUser
// @Param	id		path 	string	true		"user id"
// @Param	body		body 	users.UserDTO	true		"body for user content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id [put]
func (u *UserController) UpdateUser() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的用户为空"}
		u.ServeJSON()
		return
	}
	var f UserDTO
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &f)
	// 开始校验输入值
	valid := validation.Validation{}
	b, err := valid.Valid(&f)
	if err != nil {
		// handle error
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "严重异常" + err.Error()}
		u.ServeJSON()
		return
	}
	if !b {
		var validMsg []string
		// validation does not pass
		for _, err := range valid.Errors {
			validMsg = append(validMsg, err.Message)
			log.Println(err.Key, err.Message)
		}
		if !utils.IsEmpty(validMsg) {
			u.Data["json"] = map[string]interface{}{"code": 0, "message": strings.Join(validMsg, ",")}
			u.ServeJSON()
			return
		}
	}
	userss, err1 := GetUser(ids)
	if err1 != nil || utils.IsEmpty(userss.Username) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "员工不存在"}
		u.ServeJSON()
		return
	}
	usersn, err1 := GetUserByUserName(f.Username)
	if err1 != nil || (!utils.IsEmpty(usersn.Id) && userss.Id != usersn.Id) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "登陆账号重复"}
		u.ServeJSON()
		return
	}
	var pro UsersProfile
	pro.Realname = f.Realname
	pro.Sex = f.Sex
	pro.Birth = f.Birth
	pro.Email = f.Email
	pro.Webchat = f.Webchat
	pro.Qq = f.Qq
	pro.Phone = f.Phone
	pro.Tel = f.Tel
	pro.Address = f.Address
	pro.Emercontact = f.Emercontact
	pro.Emerphone = f.Emerphone
	pro.Departid = f.Departid
	pro.Positionid = f.Positionid
	pro.Ip = u.Ctx.Input.IP()
	err = UpdateProfile(ids, pro)
	var user Users
	user.Username = f.Username
	if f.Password != "" {
		user.Password = f.Password
	}
	err = UpdateUser(ids, user)

	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败"}
	}
	u.ServeJSON()

}

// @Title Get
// @Description get UsersProfile  by uid
// @Param	id		path 	string	true		"The key for UsersProfile"
// @Success 200 {object} users.UsersProfile
// @Failure 403 :id is empty
// @router /:id [get]
func (u *UserController) Get() {
	uid := u.GetString(":id")
	if uid != "" {
		var responseEntity cores.ResponseEntity
		int64, err := strconv.ParseInt(uid, 10, 64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
			return
		}
		usersProfile, err := GetProfile(int64)
		if err != nil {
			u.Data["json"] = responseEntity.BuildError(err.Error())
		} else {
			u.Data["json"] = responseEntity.Build(usersProfile).Data
			u.Ctx.Output.Status = responseEntity.StatusCode
		}
	}
	u.ServeJSON()
}

// @Title Update User status
// @Description  Update User status
// @Param	id		path 	string	true		"User id"
// @Param	status	query 	string	true		"User 状态"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/status [put]
func (u *UserController) UpdateUserStatus() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的用户为空"}
		u.ServeJSON()
		return
	}
	status, err := u.GetInt("status")
	if err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "状态为空"}
		u.ServeJSON()
		return
	}
	exist, err1 := GetUser(ids)
	if err1 != nil || utils.IsEmpty(exist.Username) {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "用户不存在"}
		u.ServeJSON()
		return
	}
	err = ChangeUserStatus(ids, status)
	if err == nil {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "信息修改成功", "id": fmt.Sprintf("%d", ids)}
	} else {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "信息修改失败"}
	}
	u.ServeJSON()
}

type UserPwdDTO struct {
	OldPassword string
	NewPassword string
	Confpwd     string
}

// @Title UpdateUserPwd
// @Description  UpdateUserPwd
// @Param	id		path 	string	true		"user id"
// @Param	body		body 	users.UserPwdDTO	true		"body for user content"
// @Success 200 {string} 更新成功
// @Failure 403 body is empty
// @router /:id/pwd [put]
func (u *UserController) UpdateUserPwd() {
	ids, err := u.GetInt64(":id")
	if err != nil || ids <= 0 {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "你选择更新的用户为空"}
		u.ServeJSON()
		return
	}
	var f UserPwdDTO
	err = json.Unmarshal(u.Ctx.Input.RequestBody, &f)
	oldpwd := f.NewPassword
	if "" == oldpwd {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请填写当前密码"}
		u.ServeJSON()
		return
	}
	newpwd := f.NewPassword
	if "" == newpwd {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请填写新密码"}
		u.ServeJSON()
		return
	}
	confpwd := f.Confpwd
	if "" == confpwd {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "请填写确认密码"}
		u.ServeJSON()
		return
	}
	if confpwd != newpwd {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "两次输入密码不一致"}
		u.ServeJSON()
		return
	}
	userid := u.BaseController.UserUserId
	err = UpdatePassword(userid, f.OldPassword, f.NewPassword)
	if err != nil {
		u.Data["json"] = map[string]interface{}{"code": 0, "message": "原密码不正确"}
		u.ServeJSON()
		return
	} else {
		u.Data["json"] = map[string]interface{}{"code": 1, "message": "密码修改成功", "id": fmt.Sprintf("%d", ids)}
		u.ServeJSON()
	}

}
